package com.yanqu.road.server.manager.activity.suitang.manager;

import com.yanqu.road.entity.activity.suitang.config.SuiTangConfigSync;
import com.yanqu.road.entity.activity.suitang.data.CrossSuiTangData;
import com.yanqu.road.entity.activity.suitang.data.CrossSuiTangUnionJoinData;
import com.yanqu.road.entity.activity.suitang.entity.group.CrossSuiTangGroup;
import com.yanqu.road.entity.activity.suitang.entity.rank.CrossSuiTangRank;
import com.yanqu.road.entity.activity.suitang.entity.rank.CrossSuiTangRankListModel;
import com.yanqu.road.entity.activity.suitang.enums.eSuiTangCityType;
import com.yanqu.road.entity.activity.suitang.enums.eSuiTangWarType;
import com.yanqu.road.entity.union.activitygroup.UnionActivityGroup;
import com.yanqu.road.entity.union.activitygroup.UnionActivityGroupUnion;
import com.yanqu.road.server.manager.union.activitygroup.Cross2UnionActivityGroupMgr;
import com.yanqu.road.utils.RandomHelper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/*
 * 分组管理
 */
public class CrossSuiTangGroupActivityMgr extends CrossBaseActivityMgr {

    protected static Logger logger = LogManager.getLogger(CrossSuiTangGroupActivityMgr.class.getName());

    @Override
    public void init() {
        super.init();
    }

    /*
     * 商会活动内分组
     */
    public void groupUnion() {
        if (activity == null) {
            return;
        }
        SuiTangConfigSync config = activity.getConfig();
        if (config == null) {
            return;
        }
        int activityId = config.getActivityId();
        int groupId = activity.getGroupId();
        UnionActivityGroup groupData = Cross2UnionActivityGroupMgr.getGroupData(activityId, groupId);
        if (groupData == null || !Cross2UnionActivityGroupMgr.haveGroup(activityId)) {
            // 分组还没出来
            return;
        }
        CrossSuiTangData crossSuiTangData = activity.getCrossSuiTangData();
        if (crossSuiTangData == null || !crossSuiTangData.getLockUnion()) {
            // 名单未锁
            return;
        }
        Map<String, CrossSuiTangUnionJoinData> unionJoinDataMap = activity.getUnionJoinDataMap();
        if (unionJoinDataMap == null || unionJoinDataMap.isEmpty()) {
            return;
        }

        List<List<Integer>> suiTangGroupChamberNumPromotion = config.getParamConfig().getSuiTangGroupChamberNumPromotion();
        if (suiTangGroupChamberNumPromotion.isEmpty()) {
            return;
        }
        int round = calcRound();
        ConcurrentHashMap<String, UnionActivityGroupUnion> unionDataMap = groupData.getUnionDataMap();
        if (unionDataMap.isEmpty() || unionDataMap.size() <= 0) {
            // 商会分组有问题
            return;
        }

        // 准备分组必要的数据
        Map<eSuiTangWarType, List<CrossSuiTangRank>> groupInfoMap = new HashMap<>();
        List<CrossSuiTangRank> unionList1 = new LinkedList<>();
        List<CrossSuiTangRank> unionList2 = new LinkedList<>();
        List<CrossSuiTangRank> unionList3 = new LinkedList<>();

        if (round == 1) {
            CrossSuiTangRankListModel unionRankMap = new CrossSuiTangRankListModel();
            // 先对加入商会按照赚速进行排名；v6.9 改为赚钱
            for (CrossSuiTangUnionJoinData value : unionJoinDataMap.values()) {
                unionRankMap.rankChange(new CrossSuiTangRank(value.getUnionUid(), 1, value.getUnionBaseInfo().getTotalPatronsAbility().longValue(), System.currentTimeMillis()));
            }
            // 首轮全部分入义军战场
            groupInfoMap.put(eSuiTangWarType.WAR_TYPE_YIJUN, unionRankMap.getRankList());
        }
        if (round > 1) {
            // 首先按照排名分战场
            Map<eSuiTangWarType, Map<Integer, CrossSuiTangRankListModel>> warUnionRankMap = activity.getWarUnionRankMap();
            for (Map.Entry<eSuiTangWarType, Map<Integer, CrossSuiTangRankListModel>> entry : warUnionRankMap.entrySet()) {
                // 晋级处理
                for (CrossSuiTangRankListModel rank : entry.getValue().values()) {
                    if (entry.getKey().getType() == eSuiTangWarType.WAR_TYPE_YIJUN.getType()) {
                        int size = Math.min(suiTangGroupChamberNumPromotion.get(round - 2).get(0), rank.getRankList().size());
                        unionList1.addAll(rank.getRankList().subList(size, rank.getRankList().size()));
                        unionList2.addAll(rank.getRankList().subList(0, size));
                    } else if (entry.getKey().getType() == eSuiTangWarType.WAR_TYPE_XIAOQI.getType()) {
                        int sizeJinJun = Math.min(suiTangGroupChamberNumPromotion.get(round - 2).get(1), rank.getRankList().size());
                        unionList2.addAll(rank.getRankList().subList(sizeJinJun, rank.getRankList().size()));
                        unionList3.addAll(rank.getRankList().subList(0, sizeJinJun));
                    }
                }
            }
            groupInfoMap.put(eSuiTangWarType.WAR_TYPE_YIJUN, unionList1);
            groupInfoMap.put(eSuiTangWarType.WAR_TYPE_XIAOQI, unionList2);
            groupInfoMap.put(eSuiTangWarType.WAR_TYPE_JINJUN, unionList3);
        }

        grouping(groupInfoMap, round);
        logger.debug("【隋唐】分组完成");
    }

    /*
     * 分组
     */
    private void grouping(Map<eSuiTangWarType, List<CrossSuiTangRank>> groupInfoMap, int round) {
        if (groupInfoMap == null || groupInfoMap.isEmpty()) {
            return;
        }
        if (activity == null) {
            return;
        }
        SuiTangConfigSync config = activity.getConfig();
        if (config == null) {
            return;
        }
        CrossSuiTangData crossSuiTangData = activity.getCrossSuiTangData();
        if (crossSuiTangData == null) {
            return;
        }
        int suiTangGroupChamberNumMax = Math.min(12, config.getParamConfig().getSuiTangGroupChamberNumMax());
        if (suiTangGroupChamberNumMax <= 0) {
            return;
        }
        int suiTangJoinCond = config.getParamConfig().getSuiTangJoinCond();
        // 取实际参与商会数量（测试坑我，实际需求非如此，改回去）
//        int suiTangJoinCond = activity.getUnionJoinDataMap().size();
        if (suiTangJoinCond <= 0) {
            return;
        }
        List<List<Integer>> suiTangGroupChamberNumPromotion = config.getParamConfig().getSuiTangGroupChamberNumPromotion();
        if (suiTangGroupChamberNumPromotion.isEmpty()) {
            return;
        }
        List<List<Integer>> eDingNList = calcN(suiTangGroupChamberNumMax, suiTangJoinCond, suiTangGroupChamberNumPromotion);
        if (eDingNList == null || eDingNList.isEmpty()) {
            return;
        }
        logger.debug("【隋唐】额定分组：{}", eDingNList);

        for (Map.Entry<eSuiTangWarType, List<CrossSuiTangRank>> entry : groupInfoMap.entrySet()) {
            List<Integer> cityList = cityListTurn();
            eSuiTangWarType warType = entry.getKey();
            logger.debug("【隋唐】分组，战场：{}，待分配城市列表：{}", warType, cityList);
            int eDingN = eDingNList.get(round - 1).get(warType.getType() - 1);
            if (eDingN <= 0) {
                continue;
            }
            List<CrossSuiTangRank> crossSuiTangRanks = entry.getValue();
            CrossSuiTangRankListModel unionRankMap = new CrossSuiTangRankListModel();
            unionRankMap.setRankList((LinkedList<CrossSuiTangRank>) crossSuiTangRanks);
            Map<Integer, CrossSuiTangGroup> groupMap = new ConcurrentHashMap<>();
            Map<Integer, Map<eSuiTangWarType, Map<Integer, CrossSuiTangGroup>>> actGroupMap = crossSuiTangData.getActGroupMap();
            if (actGroupMap == null) {
                actGroupMap = new ConcurrentHashMap<>();
                crossSuiTangData.setActGroupMap(actGroupMap);
            }
            Map<eSuiTangWarType, Map<Integer, CrossSuiTangGroup>> warTypeMap = actGroupMap.get(round);
            if (warTypeMap == null) {
                warTypeMap = new ConcurrentHashMap<>();
                actGroupMap.put(round, warTypeMap);
            }
            warTypeMap.put(warType, groupMap);
            LinkedList<CrossSuiTangRank> listUnion = unionRankMap.getRankList();
            // [0, N] 每组分配一个
            for (int i = 0; i < eDingN && i < listUnion.size(); i++) {
                CrossSuiTangGroup group = new CrossSuiTangGroup();
                group.setActGroupId(i);
                group.setRound(round);
                group.setWarType(warType);
                group.getUnionMap().put(listUnion.get(i).getId(), cityList.get(0));
                groupMap.put(i, group);
            }
            if (eDingN >= listUnion.size()) {
                continue;
            }
            cityList = new ArrayList<>(cityList.subList(1, cityList.size()));
            for (CrossSuiTangGroup group : groupMap.values()) {
                logger.debug("【隋唐】分组，战场：{}，分组：{}, 首次分配：{}, 待分配城市列表：{}", group.getWarType(), group.getActGroupId(), group.getUnionMap(), cityList);
            }

            List<CrossSuiTangRank> list = listUnion.subList(eDingN, Math.min(listUnion.size(), eDingN * 3));
            Collections.shuffle(list);
            // [N+1, 3N] 每组分配两个
            distributeRemainingElements(
                    list.subList(0, Math.min(list.size(), eDingN)),
                    groupMap,
                    cityList,
                    suiTangGroupChamberNumMax, round, warType
            );
            if (eDingN * 2 >= listUnion.size()) {
                continue;
            }
            cityList = new ArrayList<>(cityList.subList(1, cityList.size()));
            for (CrossSuiTangGroup group : groupMap.values()) {
                logger.debug("【隋唐】分组，战场：{}，分组：{}, 2次分配：{}, 待分配城市列表：{}", group.getWarType(), group.getActGroupId(), group.getUnionMap(), cityList);
            }

            distributeRemainingElements(
                    list.subList(eDingN, Math.min(list.size(), eDingN * 2)),
                    groupMap,
                    cityList,
                    suiTangGroupChamberNumMax, round, warType
            );
            cityList = new ArrayList<>(cityList.subList(1, cityList.size()));
            for (CrossSuiTangGroup group : groupMap.values()) {
                logger.debug("【隋唐】分组，战场：{}，分组：{}, 3次分配：{}, 待分配城市列表：{}", group.getWarType(), group.getActGroupId(), group.getUnionMap(), cityList);
            }
            if (eDingN * 3 >= listUnion.size()) {
                continue;
            }

            list = listUnion.subList(3 * eDingN, listUnion.size());
            Collections.shuffle(list);
            int remaining = 0;
            while (remaining < list.size()) {
                distributeRemainingElements(
                        list.subList(remaining, Math.min(list.size(), remaining + eDingN)),
                        groupMap, cityList, suiTangGroupChamberNumMax, round, warType
                );
                remaining += eDingN;
                if (cityList.isEmpty()) {
                    break;
                }
                cityList = new ArrayList<>(cityList.subList(1, cityList.size()));
            }
            for (CrossSuiTangGroup group : groupMap.values()) {
                logger.debug("【隋唐】分组，战场：{}，分组：{}, 最终分配：{}, 待分配城市列表：{}", group.getWarType(), group.getActGroupId(), group.getUnionMap(), cityList);
            }
        }
        crossSuiTangData.setUpdateOption();
    }

    /*
     * 城市随机顺序轮换
     */
    public List<Integer> cityListTurn() {
        List<Integer> cityListByType = activity.getCityActivityMgr().getCityListByType(eSuiTangCityType.CITY_TYPE_HOME.getType());
        List<Integer> ret = new ArrayList<>();
        int next = activity.getRandomHelper().next(0, cityListByType.size());
        for (Integer cityId : cityListByType) {
            ret.add((cityId + next) % 1013 + (cityId + next) / 1013 * 1001);
        }
        logger.debug("【隋唐】城市轮换：{}", ret);
        return ret;
    }

    /*
     * 分配剩余元素
     */
    private void distributeRemainingElements(
            List<CrossSuiTangRank> sublist,
            Map<Integer, CrossSuiTangGroup> groups,
            List<Integer> cityList,
            int limit, int round, eSuiTangWarType warType) {
        Collections.shuffle(sublist); // 打乱子列表以随机分配元素
        List<Integer> availableGroups = new ArrayList<>(groups.keySet());
        for (int i = 0; i < sublist.size(); i++) {
            boolean added = false;

            // Collections.shuffle(availableGroups); // 打乱组列表，以随机选择组
            if (groups.get(availableGroups.get(i)).getUnionMap().size() < limit) {
                groups.get(availableGroups.get(i)).setActGroupId(availableGroups.get(i));
                groups.get(availableGroups.get(i)).setWarType(warType);
                groups.get(availableGroups.get(i)).setRound(round);
                groups.get(availableGroups.get(i)).getUnionMap().put(sublist.get(i).getId(), cityList.get(0));
                continue;
            }

            // 如果所有组都已满，无法再添加更多元素
            if (!added) break;
        }
    }

    /*
     * 计算额定组数 N
     */
    private List<List<Integer>> calcN(int groupNumMax, int joinCond, List<List<Integer>> numPromotion) {
        if (numPromotion == null || numPromotion.isEmpty() || groupNumMax <= 0 || joinCond <= 0) {
            return null;
        }
        List<List<Integer>> eDingNList = new ArrayList<>();
        List<List<Integer>> eDingNumList = new ArrayList<>();
        int roundMax = 3;
        for (int i = 0; i < roundMax; i++) {
            List<Integer> list = new ArrayList<>();
            List<Integer> numList = new ArrayList<>();
            int yiJunWarNum = i == 0 ? joinCond : eDingNumList.get(i - 1).get(0);    // 义军战场前一天的额定人数
            int xiaoQiWarNum = i == 0 ? i : eDingNumList.get(i - 1).get(1);   // 骁骑战场前一天的额定人数
            int yiJunUp = i == 0 ? i : numPromotion.get(i - 1).get(0) * eDingNList.get(i - 1).get(0);   // 义军战场的晋级人数
            int xiaoQiUp = i == 0 ? i : numPromotion.get(i - 1).get(1) * eDingNList.get(i - 1).get(1);  // 骁骑战场的晋级人数
            list.add((int)Math.ceil((double) (yiJunWarNum - yiJunUp) / (double) groupNumMax));    // 战场人数 = 前一天人数 - 晋级人数
            list.add(i == 0 ? 0 : (int)Math.ceil((double) (xiaoQiWarNum - xiaoQiUp + yiJunUp) / (double)groupNumMax));    // 战场人数 = 前一天人数 - 晋级人数 + 低级战场晋级人数
            list.add(i == 0 || i == 1 ? 0 : (int)Math.ceil((double) xiaoQiUp / (double) groupNumMax));
            numList.add(i == 0 ? yiJunWarNum : yiJunWarNum - yiJunUp);
            numList.add(i == 0 ? 0 : xiaoQiWarNum - xiaoQiUp + yiJunUp);
            numList.add(i == 0 ? 0 : xiaoQiUp);
            eDingNList.add(list);
            eDingNumList.add(numList);
        }
        return eDingNList;
    }
}
